<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      //重新定义对象
      function observer(target) {
        //如果被观察的对象不是object类型或为null则直接返回，不能监听
        if (typeof target !== "object" || target === null) {
          return target;
        }
        //遍历对象中所有的key
        for (let key in target) {
          console.log(key);
          defineProp(target, key, target[key]); //重新定义属性
        }
      }

      //定义属性
      function defineProp(target, key, value) {
        //如果value仍然是object类型，则继续拆开监听,递归
        if (typeof value === "object") {
          observer(value);
        } else {
          Object.defineProperty(target, key, {
            get() {
              console.log("更新界面,get", target, key, value);
              return value;
            },
            set(newValue) {
              console.log("更新界面,set", target, key, value, newValue);
              value = newValue;
            },
          });
        }
      }

      //原始对象
      var user = {
        name: "jack",
        age: 19,
        sex: "男",
        address: { city: "zhuhai" },
      };
      //重新定义对象中的所有属性，拦截get与set操作，插入要执行的用户逻辑
      observer(user);

      user.address.city = "珠海";
      console.log(user.address.city);
    </script>
  </body>
</html>
